<template>
  <div class>
    <component
      :is="componentName"
      :title="form_title"
      top="5vh"
      append-to-body
      :close-on-click-modal="close_on_click_modal"
      :close-on-press-escape="close_on_press_escape"
      :visible.sync="displayPopoForm"
      :width="form_width"
      @close="onClose"
    >
      <slot name="header" :popoform="this"></slot>
      <el-form ref="form" :model="formData" :rules="rules" v-bind="formProps">
        <slot name="formBefore" :popoform="this"></slot>
        <el-row v-bind="elrowProps">
          <slot name="componentBefore" :popoform="this"></slot>
          <el-col
            v-for="(cmt, cmt_index) in component_list"
            :span="cmt.elcolOpt.span"
            :offset="cmt.elcolOpt.offset"
            :push="cmt.elcolOpt.push"
            :pull="cmt.elcolOpt.pull"
            :tag="cmt.elcolOpt.tag"
            v-if="!cmt.hiddenCol"
          >
            <!-- <el-form-item :prop="cmt.name || ''" :label="cmt.label"> -->
            <template v-if="cmt.slotName == null">
              <form-item
                :ref="'form_item_' + cmt.name"
                :component="cmt.component"
                :item="cmt"
                :form-data="formData"
                v-model="formData[ cmt.name]"
                @input="(val)=>{ dataChange( val, cmt, cmt_index);}"
                @notifyOtherComponent="notifyOtherComponent"
                @asynNotify="( status) => { asynNotify( cmt, status);}"
                @componentNotify="(type, data) => { componentNotify( type, data);}"
              ></form-item>
            </template>
            <template v-if="cmt.slotName != null">
              <slot :name="cmt.slotName" :popoform="me"></slot>
            </template>
            <!-- </el-form-item> -->
          </el-col>
          <slot name="componentAfter" :popoform="this"></slot>
        </el-row>
        <slot name="formAfter" :popoform="this"></slot>
      </el-form>

      <div class="valid_bottom_msg" v-if="!formProps.disabledBottomErrorMessage">
        <el-alert
          type="error"
          class="popform-alert"
          show-icon
          :title="msg"
          v-if="formValidMsgs.length > 0"
          v-for="(msg) in formValidMsgs"
        ></el-alert>
      </div>
      <slot name="footer" :popoform="this"></slot>
      <div :style="{textAlign: formProps.buttonAlign}" v-if="!formProps.disabledAllButton">
        <span slot="footer" class="dialog-footer">
          <template>
            <el-button
              v-for="(btn, btnIndex) in customButtons"
              :key="btnIndex"
              @click="handleCustomButtonEvent(btn, btnIndex, 'click')"
              :type="btn.type || 'default'"
            >{{btn.text}}</el-button>
          </template>
          <template v-if="!formProps.disabledProcessButton">
            <el-button @click="handleCancel" :loading="buttonLoading">{{cancel_button_text}}</el-button>
            <el-button type="primary" @click="handleSave" :loading="buttonLoading">{{confirm_button_text}}</el-button>
          </template>
        </span>
      </div>
    </component>
  </div>
</template>

<script>
  import { Element, Message, Dialog } from "element-ui";
  import staticDiv from "./components/staticDiv";
  import city from "./utils/city";
  import PopoEvent from "./utils/PopoEvent";
  import PopoAutoView from "./utils/PopoAutoView";
  import { server_request } from "./utils/request";
  import default_components from "./config/component_list";
  import { objectAssign } from "./utils/common";

  /** 默认的UI配置信息，可通过props，或者 */
  var _default_config = {
    elrowOptions: {
      gutter: 10,
      type: "",
      justify: "start",
      align: "top",
      tag: "div",
    },
    elcolOptions: {
      span: 24,
      offset: 0,
      push: 0,
      pull: 0,
      tag: "div",
    },
    formOptions: {
      labelWidth: "auto",
      labelPosition: "left",
      labelTextAlignRight: true,
      size: "",
      disabledProcessButton: false,
      disabledAllButton: false,
      disabledBottomErrorMessage: false, // 是否要隐藏底部的错误信息（位于保存按钮上方，表单元素下方）
      buttonAlign: "center",
    },
  };

  /**
   * 视图布局方面的，可以通过props进行配置
   *
   * 和表单组件有关的，则只能通过调用函数进行配置
   *
   */
  export default {
    name: "PopoForm",
    version: "2.5",
    // 所使用的ElementUI版本
    elementuiVersion: "2.13.2",
    props: {
      // 是否使用Dialog模式
      useDialog: { type: Boolean, default: true },
      // 是否开启自动视图模式
      autoView: { type: Boolean, default: false },
      // 确定按钮文本
      confirmButtonText: { type: String, default: "保存" },
      // 取消按钮文本
      cancelButtonText: { type: String, default: "取消" },
      // 点击黑蒙版层是否关闭弹窗
      closeOnClickModal: { type: Boolean, default: false },
      // 按Esc键是否关闭弹窗
      closeOnPressEscape: { type: Boolean, default: false },
      // 弹窗宽度
      width: { type: String, default: "500px" },
      // 弹窗title
      title: { type: String, default: "" },
      // 用于布局的 el-row的配置项
      elrowOptions: { type: Object, default: () => ({}) },
      // 用于Form的配置项
      formOptions: { type: Object, default: () => ({}) },
      // 添加的地址
      addUrl: { type: String, default: "" },
      // 修改的地址
      updateUrl: { type: String, default: "" },

      // 保存成功时的提示语
      successText: { type: String, default: "保存成功" },
      // 保存失败时的提示语
      failText: { type: String, default: "保存失败" },
    },
    computed: {
      componentName() {
        return this.form_use_dialog ? "dialogMode" : "staticMode";
      },
    },
    components: {
      dialogMode: Dialog,
      staticMode: staticDiv,
      formItem: {
        name: "form-item",
        functional: true,
        render: function (createElement, context) {
          // console.log( "teminput render", context);
          var props = context.props;
          var data = context.data;
          var component = props.component;

          return createElement(component, data);
        },
      },
    },
    data() {
      return {

        me: null,

        // open 方法传入的原始 config 对象
        config_source: {},

        // 当前组件所使用的 config 对象 （被处理过后的）
        config: {},

        // 事件处理对象
        popoEvent: null,

        // 插件集合
        popoPlugs: [],

        // 自定义按钮集
        customButtons: [],

        // 显示弹窗
        displayPopoForm: false,

        // 在保存成功后是否自动关闭弹窗
        autoClose: true,

        // 保存和取消按钮的loading状态
        buttonLoading: false,

        dialogLoading: false,

        // 提交前的二次确认弹窗内容
        saveConfirmWord: "",

        form_title: this.title,
        form_width: this.width,

        success_text: this.successText,
        fail_text: this.failText,

        // 视图模式转成编辑模式时按钮的文字
        view_to_edit_button_text: "编辑",
        confirm_button_text: this.confirmButtonText,
        cancel_button_text: this.cancelButtonText,
        close_on_click_modal: this.closeOnClickModal,
        close_on_press_escape: this.closeOnPressEscape,

        add_url: this.addUrl,
        update_url: this.updateUrl,

        // 是否使用 el-dialog 模式（弹窗模式）
        form_use_dialog: this.useDialog,

        // 是否使用 自动视图模式
        is_auto_view: this.autoView,

        // 自动视图时，当前的视图模式
        current_auto_view_mode: "view",

        // 默认配置
        default_config: _default_config,
        // 组件列表
        component_list: [],
        // 表单数据
        formData: {},
        // 验证规则
        rules: {
          // name: [ { required: true}],
        },

        // el-row组件的参数
        elrowProps: {},
        // el-form组件的参数
        formProps: {},

        // 表单提前时的错误信息。
        // 主要解决表单过高，超出屏幕高度，但验证错误的元素在第一个，错误提示和元素本身都超出屏幕看不到，
        // 导致用户点击提交按钮时，进入假性的提交无反应状态的问题。
        // 不使用 this.$message，是避免错误信息消失太快，错误提示看不完整
        formValidMsgs: [],

        /*
                        保存当前正在进行异步处理的组件。
                        当有未完成的异步处理组件时，点击“保存”按钮将不会执行方法
                     */
        asynComponents: [],

        // 当前Open后的窗口，发出请求前，进行数据处理时的配置
        request_config: {},

        // 发出请求时的默认数据处理配置
        request_default_config: {
          // 碰到数组类型的参数时，join函数所使用的分隔符
          array_split_chat: ",",
          // 碰到Date类型的参数时，在向后台发请求时，将Date为String时的格式化串
          datetime_format: "yyyy-MM-dd hh:mm:ss",
        },
      };
    },
    mounted() {
      this.triggerPlugs("onMounted");
    },
    created() {
      this.popoEvent = new PopoEvent(this);
      this.popoPlugs.push(new PopoAutoView(this));
      this.elrowProps = objectAssign({}, _default_config.elrowOptions, this.elrowOptions);
      this.formProps = objectAssign({}, _default_config.formOptions, this.formOptions);
      // console.log( this.formProps);
      this.triggerPlugs("onCreated");
      this.me = this;
    },
    methods: {
      /**
       * 获得 PopoForm 的事件对象
       */
      getPopoEvent() {
        return this.popoEvent;
      },

      /**
       * 通知插件相关事件，包括初始化或者啥啥。
       */
      triggerPlugs() {
        var args = Array.prototype.slice.apply(arguments);
        var key = args.shift();
        this.popoPlugs.forEach((plugs) => {
          if (typeof plugs[key] == "function") {
            plugs[key].apply(this, args);
          }
        });
      },

      /**
       * 修改表单内容，这里的config和 openPromise 不一样，只需要写上要修改的部分内容就行。
       * 因为使用的是 openPromise 方法，所以返回的会是个Promise对象。
       *
       */
      changeConfig(config) {
        var conf = objectAssign({}, config, this.config_source);
        return this.__openPromise(conf);
      },

      /**
       * 显示弹窗的方法。
       * 因为该方法使用 Promise 对象，所以某些体验会更好，建议使用该方法，尽量不要使用 open 方法。
       * 原来open方法返回的事件对象，会在 Promise.then 中传入(第一个参数)，以供使用。
       *
       * @param  {[type]} config [description]
       * @return {[type]}        [description]
       */
      openPromise(config) {
        return new Promise((resolve, reject) => {
          this.releaseComponent();
          this.$nextTick(() => {
            var obj = this.open(config);
            resolve(obj);
          });
        });
      },

      /**
       * 和 openPromise 不同的是，调用的是 _open 方法，而不是 open方法。
       */
      __openPromise(config) {
        return new Promise((resolve, reject) => {
          this.releaseComponent();
          this.$nextTick(() => {
            var obj = this._open(config);
            resolve(obj);
          });
        });
      },

      /**
       * 添加自定义按钮
       */
      addButton(btn) {
        this.customButtons.push(btn);
      },

      /**
       * 删除自定义按钮
       */
      removeButton(__id) {
        var index = this.customButtons.findIndex((btn) => {
          return btn.__id == __id;
        });
        if (index >= 0) {
          this.customButtons.splice(index, 1);
        }
      },

      /**
       * 显示弹窗
       * @param  {[type]} config [description]
       * @return {[type]}        [description]
       */
      open(config) {
        this.config_source = objectAssign({}, config);
        return this._open(config);
      },

      /**
       * _open方法是使用PopoForm核心方法，独立出来方便使用。
       */
      _open(config) {
        // this.config_source = objectAssign( {}, config);
        this.clearValidate();
        this.config = this.formatConfig(config);
        this.triggerPlugs("onOpenStart", objectAssign({}, config));
        config = this.config;

        var buttons = config.buttons || [];
        buttons.forEach((btn) => {
          this.addButton(btn);
        });

        this.form_use_dialog = config.useDialog !== undefined ? config.useDialog : this.useDialog;
        // this.is_auto_view = config.autoView !== undefined ? config.autoView: this.autoView;
        // this.current_auto_view_mode = config.currentAutoViewMode !== undefined ? config.currentAutoViewMode : this.current_auto_view_mode;
        this.confirm_button_text = config.confirmButtonText || this.confirm_button_text;
        this.cancel_button_text = config.cancelButtonText || this.cancel_button_text;
        this.add_url = config.addUrl || this.add_url;
        this.update_url = config.updateUrl || this.update_url;
        this.form_title = config.title || this.form_title;
        this.form_width = config.width || this.form_width;
        this.success_text = config.successText || this.success_text;
        this.fail_text = config.failText || this.fail_text;

        var component_list = config.component_list || [];
        var formData = objectAssign({}, config.formData);
        this.elrowProps = objectAssign({}, this.elrowProps, config.elrowProps);
        this.formProps = objectAssign({}, this.formProps, config.formProps);
        this.formProps.class = { form_label_text_align: false };

        if (!!this.formProps.labelTextAlignRight) {
          this.formProps.class["form_label_text_align"] = true;
        }

        component_list = this.washComponent(component_list);
        this.logComponent(component_list);
        var rules = this.initRules(config, component_list);

        this.request_config = objectAssign({}, this.request_default_config, config.request_config);

        this.formData = formData;
        this.rules = rules;
        this.displayPopoForm = true;
        this.autoClose = config.autoClose !== undefined ? !!config.autoClose : !!this.autoClose;
        this.saveConfirmWord = config.saveConfirmWord;

        this.$nextTick( ()=>{
          this.component_list = component_list;
          this.triggerPlugs("onOpenEnd", objectAssign({}, config));
        });

        return this.popoEvent;
      },

      /**
       * 关闭弹窗
       * @return {[type]} [description]
       */
      close() {
        this.displayPopoForm = false;
      },

      /**
       * 点击取消按钮时
       */
      handleCancel() {
        this.displayPopoForm = false;
        this.popoEvent.trigger("cancel");
      },

      /**
       * 自定义按钮事件处理
       */
      handleCustomButtonEvent(btn, btnIndex, eName) {
        if (typeof btn[eName] == "function") {
          btn[eName](this);
        }
      },

      /**
       * 初始化验证规则，会根据设置，设置上必填验证
       */
      initRules(config, component_list) {
        var rules = config.rules || {};
        var requireFields = config.requireFields || "";

        if (!Array.isArray(requireFields)) {
          requireFields = requireFields.split(",");
        }

        requireFields.forEach((field, index) => {
          if (field == null) return;
          var rule = rules[field] || [];
          var component = component_list.find((item) => {
            return item.name == field;
          });
          if (component == null) return;
          rule.push({ required: true, message: "请填写" + component.getLabel() });
          rules[field] = rule;
        });

        return rules;
      },

      /**
       * 对 config 参数进行格式化操作。
       * 这里不是对具体业务的操作，而是将 config  这个配置，进行标准的格式化，
       * 以防止后续业务中，还要对统一的格式进行判 null 处理。
       */
      formatConfig(config) {
        var _list = [];
        config.component_list.forEach((cmpt) => {
          if (!cmpt.name) return;

          var names = cmpt.name.split("|");
          var label = cmpt.label;
          if( label == null ){
            label = names[1];
          }
          if( label == null ){
            label = names[0];
          }
          // var label = cmpt.label || names[1] || names[0];
          var component_name = cmpt.component || names[2] || null;

          cmpt.label = label;
          cmpt.name = names[0];
          cmpt.component = component_name;

          // 快捷属性设置
          cmpt.elcolProps = cmpt.elcolProps || {};
          if (cmpt.colspan && !cmpt.elcolProps.span) {
            cmpt.elcolProps.span = cmpt.colspan;
          }

          cmpt.props = cmpt.props || {};

          if (cmpt.placeholder !== undefined && cmpt.props.placeholder === undefined) {
            cmpt.props.placeholder = cmpt.placeholder;
          }
          if (cmpt.size !== undefined && cmpt.props.size === undefined) {
            cmpt.props.size = cmpt.size;
          }
          if (cmpt.disabled !== undefined && cmpt.props.disabled === undefined) {
            cmpt.props.disabled = cmpt.disabled;
          }
          if (cmpt.useView !== undefined && cmpt.props.useView === undefined) {
            cmpt.props.useView = cmpt.useView;
          }
          cmpt.props._useView = cmpt.props.useView;

          if (this.formProps.disabled !== undefined) {
            cmpt.props.disabled = cmpt.props.disabled || this.formProps.disabled;
          }

          if (cmpt.readonly !== undefined && cmpt.props.readonly === undefined) {
            cmpt.props.readonly = cmpt.readonly;
          }

          cmpt.component = cmpt.component || "text";
          cmpt._component_source = cmpt.component;
          cmpt.elcolOpt = objectAssign({}, _default_config.elcolOptions, cmpt.elcolProps);
          _list.push(cmpt);
        });
        config.component_list = _list;
        return config;
      },

      /**
       * 清洗component，组装必要的数据
       * @param  {[type]} component_list [description]
       * @return {[type]}                [description]
       */
      washComponent(component_list) {
        var _list = [];
        component_list.forEach((cmpt) => {
          if (typeof cmpt.component == "string") {
            // console.log( "component type", this.is_view_model ? "view" : "edit", default_components[ this.is_view_model ? "view" : "edit"]);
            var useView = !!cmpt.props.useView;
            var component = default_components[useView ? "view" : "edit"][cmpt.component];
            if (component == null) {
              component = default_components.common[cmpt.component];
            }
            cmpt.component = component;
          }

          cmpt.getLabel = () => {
            var label = cmpt.labelDisplay;
            if( label == null) label = cmpt.label;
            if( label == null) label = "该项";
            return label;
          };

          // cmpt.elcolOpt = objectAssign( {}, _default_config.elcolOptions, cmpt.elcolProps);
          _list.push(cmpt);
        });

        return _list;
      },

      /**
       * 向控制台打印组件的PHP帮助日志
       * @param  {[type]} component_list [description]
       * @return {[type]}                [description]
       */
      logComponent(component_list) {
        // return;
        var rule_logs = [];
        var name_logs = [];
        component_list.forEach((cmt) => {
          if (!cmt.props.disabled) {
            name_logs.push(cmt.name);
            rule_logs.push('"' + cmt.name + "|" + cmt.label + '" => "require",');
          }
        });

        var space = [];
        space.length = 40;
        space.fill("=");
        var space_str = space.join("");

        // 输出 php 验证规则简单版，以及字段名集合
        console.log(space_str + " php 1" + space_str);
        console.log(rule_logs.join("\n"));
        console.log(space_str + " php 2" + space_str);
        console.log(name_logs.join(","));
        console.log(space_str + " php 3" + space_str);
      },

      /**
       * 关闭时清空组件、表单数据和验证数据
       * @return {[type]} [description]
       */
      onClose() {
        // this.displayPopoForm = false;
        this.component_list = [];
        this.formData = {};
        this.rules = {};
        this.popoEvent.trigger("close");
      },

      /**
       * 清空当前的所有组件，因为连续调用 open 方法时，组件的状态不会更新，所以需要执行该方法
       * @return {[type]} [description]
       */
      releaseComponent() {
        this.component_list = [];
      },

      /**
       * 清除所有的校验信息。
       *
       * @param  {[type]} now 是否立马清除，默认为在下一次视图渲染前清除(nextTick)
       * @return {[type]}     [description]
       */
      clearValidate(now) {
        var clear = () => {
          this.formValidMsgs = [];
          if (this.$refs["form"] && this.$refs["form"].clearValidate) {
            this.$refs["form"].clearValidate();
          }
        };
        if (!now) {
          this.$nextTick(clear);
        } else {
          clear();
        }
      },

      /**
       * 当form-item 中的数据发生变化时
       *
       * @param  {[type]} val       [description]
       * @param  {[type]} cmt       [description]
       * @param  {[type]} cmt_index [description]
       * @return {[type]}           [description]
       */
      dataChange(val, cmt, cmt_index) {
        // console.log( "popoform data change", val, cmt, cmt_index);

        if (typeof cmt.onChange == "function") {
          this.$nextTick(() => {
            cmt.onChange(val, this.formData, cmt, cmt_index, this);
          });
        }
        // this.$set( this.formData, cmt.name, val);
        // this.formData[ cmt.name] = val;
      },

      /**
       * 通知指定组件，用于组件间的通信，适合场景如：多个下拉框的级联操作
       * 要接收通信的组件，必须实现 handlerNotify 方法，用以接受通知
       *
       * @param  {[type]} name   [description]
       * @param  {[type]} params [description]
       * @return {[type]}        [description]
       */
      notifyOtherComponent() {
        var args = Array.from(arguments);
        if (args.length == 0) return;

        var names = args.shift().split(",");
        var params = args;
        // console.log( "pa", args);

        names.forEach((_name) => {
          var component = this.component_list.find((cmt) => {
            return cmt.name == _name;
          });
          if (component) {
            var ref = "form_item_" + component.name;
            var refNode = this.$refs[ref];
            var node = null;
            if (refNode && refNode.length > 0) {
              node = refNode[0];
            }

            if (node && typeof node.handlerNotify == "function") {
              node.handlerNotify.apply(this, params);
            }
          }
        });
      },

      /**
       * 用于在界面上显示自定义的错误信息，可用于后台Ajax返回的验证信息
       *
       * @param  {[type]} component [description]
       * @param  {[type]} msg       [description]
       * @return {[type]}           [description]
       */
      showError(component_name, msg) {
        if (!!component_name.name) {
          component_name = component_name.name;
        }

        var elem = this.$refs["form_item_" + component_name];

        if (!!elem) {
          if (elem.length > 0) {
            elem = elem[0];
          }

          if (typeof elem.showError == "function") {
            elem.showError(msg);
          } else {
            var form_item = elem.$refs["el-form-item"];
            if (form_item) {
              form_item.validateMessage = msg;
              form_item.validateState = "error";
            }
          }
        }

        if (!this.formValidMsgs.find((_msg) => _msg == msg)) {
          this.formValidMsgs.push(msg);
        }
      },

      /**
       * 用于子组件通知自己正处于异步处理状态。
       * 只要有任何子组件还处在异步处理状态，则在 PopoForm 上点击 “保存”按钮不会有反应。
       *
       * @param  {[type]} component [description]
       * @param  {[type]} status    异步状态："doing" 处理中  "finish" 已完成
       * @return {[type]}           [description]
       */
      asynNotify(component, status) {
        // console.log( "asynNotify", component.name, status, component);
        if (status == "doing") {
          let _cmt = this.asynComponents.find((item) => {
            return component.name == item.name;
          });
          if (!_cmt) {
            this.asynComponents.push(component);
          }
        } else {
          let index = this.asynComponents.findIndex((item) => {
            return component.name == item.name;
          });
          this.asynComponents.splice(index, 1);
        }
      },

      /**
       * 该方法可用于接收由子组件传递过来的消息，根据消息进行相应操作。
       * 目前支持的有：
       * 1. 添加rules校验（在ElFormItem上添加rules的话，会覆盖掉ElForm上的rules规则）
       *
       * @param   {[type]}  type  消息类型
       * @param   {[type]}  data  消息数据
       *
       * @return  {[type]}        [return description]
       */
      componentNotify(type, data) {
        /*
            添加验证规则，data格式为： {field: "字段name", rules: []}
            rules属性必须是数组。
          */
        if (type == "addRule") {
          var field = data.field;
          if (!field) return;
          if (this.rules[field] == null) {
            this.rules[field] = [];
          }
          data.rules.forEach((rule) => {
            this.rules[field].push(rule);
          });
        }
      },

      /**
       * 点击保存的方法
       *
       * @return {[type]} [description]
       */
      handleSave() {
        this.clearValidate(true);

        if (this.asynComponents.length > 0) {
          var component = this.asynComponents[0];
          var msg = (component && component.label ? component.label : "") + "正在处理中...";
          this.$message(msg);
          return;
        }

        this.$refs["form"].validate((valid, validResult) => {
          if (!valid) {
            // console.log( "valid", valid, validResult);
            // this.formValidMsgs = [];
            var msgs = [];
            for (var k in validResult) {
              var ret = validResult[k];
              if (ret.length > 0) {
                msgs = msgs.concat(ret.map((r) => r.message + ""));
                // msgs.push( ret[0].message);
              }
            }
            this.$nextTick(() => {
              this.formValidMsgs = msgs.slice(0);
            });
            return;
          }

          this.formValidMsgs = [];

          if (!!this.saveConfirmWord) {
            this.$confirm(this.saveConfirmWord, "提示", {}).then(() => {
              this._save();
            });
          } else {
            this._save();
          }
        });
      },

      _save() {
        var is_update = !!this.formData.id;
        var url = is_update ? this.update_url : this.add_url;

        // 请求前预处理请求数据，并使用最后的有效返回值作为 formData 数据
        let formData = objectAssign( {}, this.formData);
        let processData = this.popoEvent.trigger( "processFormData", formData);
        if( processData && processData.length > 0){
          let _data = processData.pop();
          while( _data == null && processData.length > 0){
            _data = processData.pop();
          }
          if( _data){
            formData = _data;
          }
        }

        if (!url) {
          /*
            如果没有配置 updateUrl 或者 addUrl，则直接调用 complete 函数
            并传回FormData对象。这样可以应对一结非cu操作的需求。
          */
          // debugger;
          this.popoEvent.trigger("complete", objectAssign({}, formData));

          if (this.autoClose && this.form_use_dialog ) {
            this.close();
          }
          return;
        }

        this.buttonLoading = true;
        // this.dialogLoading = true;
        // return;
        server_request(url, formData, "post", this.request_config)
          .then((res) => {
            this.buttonLoading = false;
            this.dialogLoading = false;
            // console.log( "ret result", res);
            if (res.code == 200) {
              this.$message.success(this.success_text);
              this.popoEvent.trigger("success", res, formData);

              if (this.autoClose && this.form_use_dialog ) {
                this.close();
              }
            } else if (res.code == 50110) {
              // 后台返回的验证错误信息
              var valid_msg = res.data;
              if (!(valid_msg instanceof Array)) {
                valid_msg = [valid_msg];
              }

              valid_msg.forEach((vmsg) => {
                this.showError(vmsg.name, vmsg.message);
              });
            } else {
              this.$message.error(res.message || this.fail_text);
              console.error("PopoForm 保存失败", res);
              this.failFn(res, null);
            }
          })
          .catch((e) => {
            this.buttonLoading = false;
            this.dialogLoading = false;
            console.error("PopoForm 抛出异常", e);
            this.$message.error(this.fail_text);
            this.popoEvent.trigger("fail", e);
          });
      },
    },
  };
</script>

<style scoped lang="scss">
::v-deep {
  .el-form-item__label {
    // font-size: 16px;
    // float: none;
  }

  .form_label_text_align .el-form-item__label {
    text-align: right;
  }
  .el-dialog__body {
    padding: 10px 20px;
  }
  .valid_bottom_msg .el-alert {
    margin-bottom: 5px;
  }
}
</style>
